﻿using EPiServer.Core.Html.StringParsing;

namespace ElencySolutions.MultipleProperty
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.IO.Compression;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using CustomProperties;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.Core.PropertySettings;
    using EPiServer.DataAbstraction;
    using EPiServer.SpecializedProperties;

    /// <summary>
    /// Multiple Property Helper
    /// </summary>
    public static class MultiplePropertyHelper
    {

        private const string PropertyName = "MPFake_989A7C38-20B5-4A2E-9895-641AABD34086";

        /// <summary>
        /// Determines whether the specified entity is list.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>
        ///   <c>true</c> if the specified entity is list; otherwise, <c>false</c>.
        /// </returns>
        internal static bool IsList<TEntity>(TEntity entity)
        {
            return entity is IList;
        }

        /// <summary>
        /// Gets the type of the singular entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        internal static Type GetSingularEntityType<TEntity>(TEntity entity)
        {
            Type entityType = typeof(TEntity);

            if (IsList(entity))
            {
                //entityType = entity.GetType().GetGenericArguments()[0];
                entityType = entity.GetType().BaseType.GetGenericArguments()[0];
            }

            return entityType;
        }

        /// <summary>
        /// Gets the properties.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        internal static List<PropertyInfo> GetProperties<TEntity>(TEntity entity)
        {
            Type type = entity.GetType();

            if (IsList(entity))
                type = GetSingularEntityType(entity);

            return GetEntityTypeProperties(type);
        }

        internal static List<PropertyInfo> GetEntityTypeProperties(Type entityType)
        {
            List<PropertyInfo> properties = entityType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).ToList();
            return properties
                .Where(current => HasEntityPropertyAttribute(current)
                    && (GetEntityPropertyAttribute(current).Type != null && GetEntityPropertyAttribute(current).Type.IsSubclassOf(typeof(PropertyData))))
                    .OrderBy(current => GetEntityPropertyAttribute(current).SortIndex).ToList();
        }

        /// <summary>
        /// Gets the entity attribute.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <returns></returns>
        internal static MultiplePropertyEntityAttribute GetEntityAttribute(Type entityType)
        {
            return entityType.GetCustomAttributes(typeof(MultiplePropertyEntityAttribute), false)[0] as MultiplePropertyEntityAttribute;
        }

        /// <summary>
        /// Determines whether the entity has an entity attribute.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <returns>
        ///   <c>true</c> if the entity has an entity attribute; otherwise, <c>false</c>.
        /// </returns>
        internal static bool HasEntityAttribute(Type entityType)
        {
            return entityType.GetCustomAttributes(typeof(MultiplePropertyEntityAttribute), false).Count() > 0;
        }

        /// <summary>
        /// Determines whether the entity has a data contract.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <returns>
        ///   <c>true</c> if the entity has a data contract; otherwise, <c>false</c>.
        /// </returns>
        internal static bool HasDataContract(Type entityType)
        {
            if (IsList(Activator.CreateInstance(entityType)))
                return entityType.GetCustomAttributes(typeof(CollectionDataContractAttribute), false).Count() > 0;
            
            return entityType.GetCustomAttributes(typeof(DataContractAttribute), false).Count() > 0;
        }

        /// <summary>
        /// Determines whether the entity has been decorated with the known type attribute.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <returns>
        ///   <c>true</c> if  the entity has been decorated with the known type attribute; otherwise, <c>false</c>.
        /// </returns>
        internal static bool HasKnownType(Type entityType)
        {
            KnownTypeAttribute knownType = entityType.GetCustomAttributes(typeof(KnownTypeAttribute), false)
                .Where(current => ((KnownTypeAttribute)current).Type.Equals(entityType))
                .FirstOrDefault() as KnownTypeAttribute;

            if (knownType == null || knownType.Type == null)
                return false;

            return knownType.Type.Equals(entityType);
        }

        /// <summary>
        /// Gets the entity property attribute.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns></returns>
        internal static MultiplePropertyEntityPropertyAttribute GetEntityPropertyAttribute(PropertyInfo property)
        {
            return property.GetCustomAttributes(typeof(MultiplePropertyEntityPropertyAttribute), false)[0] as MultiplePropertyEntityPropertyAttribute;
        }

        /// <summary>
        /// Determines whether the property has an EntityPropertyAttribute.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>
        ///   <c>true</c> if the property has an EntityPropertyAttribute; otherwise, <c>false</c>.
        /// </returns>
        internal static bool HasEntityPropertyAttribute(PropertyInfo property)
        {
            return property.GetCustomAttributes(typeof(MultiplePropertyEntityPropertyAttribute), false).Count() > 0;
        }

        /// <summary>
        /// Gets the add button text.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <returns></returns>
        internal static string GetAddButtonText(MultiplePropertyEntityAttribute attribute)
        {
            string text = attribute.AddButtonText;

            if (!string.IsNullOrEmpty(attribute.AddButtonTextTranslationKey))
                text = LanguageManager.Instance.TranslateFallback(attribute.AddButtonTextTranslationKey, attribute.AddButtonText);

            if (string.IsNullOrEmpty(text))
                text = LanguageHelper.Translate("/elencySolutionsMultipleProperty/addNew");

            return text;
        }

        /// <summary>
        /// Gets the information header text.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <returns></returns>
        internal static string GetInformationHeaderText(MultiplePropertyEntityAttribute attribute)
        {
            string text = attribute.ListItemInformationHeader;

            if (!string.IsNullOrEmpty(attribute.AddButtonTextTranslationKey))
                text = LanguageManager.Instance.TranslateFallback(attribute.ListItemInformationHeaderTranslationKey, attribute.ListItemInformationHeader);

            return text;
        }

        /// <summary>
        /// Gets the caption.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <returns></returns>
        internal static string GetCaption(MultiplePropertyEntityPropertyAttribute attribute)
        {
            string labelText = attribute.Caption;

            if (!string.IsNullOrEmpty(attribute.CaptionTranslationKey))
                labelText = LanguageManager.Instance.TranslateFallback(attribute.CaptionTranslationKey, attribute.Caption);

            return labelText;
        }

        /// <summary>
        /// Gets the description.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        internal static string GetDescription<TEntity>(TEntity entity)
        {
            PropertyInfo descriptionProperty = GetDescriptionProperty(entity);

            if (descriptionProperty == null || string.IsNullOrEmpty(GetCaption(GetEntityPropertyAttribute(descriptionProperty))))
                return string.Empty;

            return GetCaption(GetEntityPropertyAttribute(descriptionProperty));
        }

        /// <summary>
        /// Gets the description property.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        internal static PropertyInfo GetDescriptionProperty<TEntity>(TEntity entity)
        {
            List<PropertyInfo> properties = GetProperties(entity);
            return properties.Where(current => GetEntityPropertyAttribute(current).IsInformationProperty).FirstOrDefault();
        }

        /// <summary>
        /// Gets the tab names.
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="tabs">The tabs.</param>
        /// <returns></returns>
        internal static List<string> GetTabNames(List<PropertyInfo> properties, out List<IMultiplePropertyTab> tabs)
        {
            tabs = properties
                .Select(current => GetTab(GetEntityPropertyAttribute(current)))
                .Where(tab => tab != null)
                .ToList();

            return properties
                .Select(current => GetTab(GetEntityPropertyAttribute(current)))
                .Where(tab => tab != null)
                .OrderBy(tab => tab.TabIndex)
                .Select(GetTabName)
                .Where(tabName => !string.IsNullOrEmpty(tabName))
                .Distinct()
                .ToList();
        }

        /// <summary>
        /// Gets the name of the tab.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <returns></returns>
        internal static string GetTabName(MultiplePropertyEntityPropertyAttribute attribute)
        {
            return GetTabName(GetTab(attribute));
        }

        /// <summary>
        /// Gets the tab.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <returns></returns>
        internal static IMultiplePropertyTab GetTab(MultiplePropertyEntityPropertyAttribute attribute)
        {
            if (attribute.Tab == null)
                return null;

            if (attribute.Tab.GetInterfaces().Count(current => current.Equals(typeof(IMultiplePropertyTab))) == 0)
                throw new Exception("A multiple property tab must implement interface IMultiplePropertyTab.");

            return Activator.CreateInstance(attribute.Tab) as IMultiplePropertyTab;
        }

        /// <summary>
        /// Gets the name of the tab.
        /// </summary>
        /// <param name="tab">The tab.</param>
        /// <returns></returns>
        internal static string GetTabName(IMultiplePropertyTab tab)
        {
            if (tab == null)
                return string.Empty;

            string tabName = tab.TabName;

            if (!string.IsNullOrEmpty(tab.TabNameTranslationKey))
                tabName = LanguageManager.Instance.TranslateFallback(tab.TabNameTranslationKey, tab.TabName);

            return tabName;
        }

        internal static Control FindControlRecurisve(Control parent, string id, bool useClientId, bool useUniqueId = false)
        {
            Control foundControl = null;

            foreach (Control control in parent.Controls)
            {
                bool match;

                if (useClientId)
                    match = control.ClientID == id;
                else if (useUniqueId)
                    match = control.UniqueID == id;
                else
                    match = control.ID == id;

                if (match)
                {
                    foundControl = control;
                    return foundControl;
                }

                foundControl = FindControlRecurisve(control, id, useClientId, useUniqueId);

                if (foundControl != null)
                    return foundControl;
            }

            return foundControl;
        }

        internal static T FindControlOfType<T>(Control parent) where T : Control
        {
            T foundControl = null;

            foreach (Control control in parent.Controls)
            {
                if (control is T)
                {
                    foundControl = (T)control;
                    return foundControl;
                }

                foundControl = FindControlOfType<T>(control);

                if (foundControl != null)
                    return foundControl;
            }

            return foundControl;
        }

        internal static Control GetTopLevelMultiplePropertyControl(Control control)
        {
            Control foundControl = null;

            if (control is IMultiplePropertyControl)
                foundControl = control;

            if (control.Parent != null)
            {
                Control c = GetTopLevelMultiplePropertyControl(control.Parent);

                if (c != null)
                    foundControl = c;
            }

            return foundControl;
        }

        internal static void FindControlsOfType<T>(Control parent, List<Control> foundControls)
        {
            foreach (Control control in parent.Controls)
            {
                if (control is T)
                    foundControls.Add(control);

                FindControlsOfType<T>(control, foundControls);
            }
        }

        internal static void FindControlsWhereTypeNameContainsText(Control parent, List<Control> foundControls, string text)
        {
            foreach (Control control in parent.Controls)
            {
                if (control.GetType().FullName.ToLower().Contains(text.ToLower()))
                    foundControls.Add(control);

                FindControlsWhereTypeNameContainsText(control, foundControls, text);
            }
        }

        internal static Control GetTopLevelContainerTableCell(Control control)
        {
            Control container = null;
            Control parent = control.Parent;

            while  (parent != null)
            {
                if (parent is HtmlTableCell)
                    container = parent;

                parent = parent.Parent;
            }

            if (container !=null && string.IsNullOrEmpty(container.ClientID))
                container = null;

            return container;
        }

        #region Serialization methods

        /// <summary>
        /// Serialize an object into an XML string.
        /// </summary>
        /// <typeparam name="TSerializationType">The type of the serialization type.</typeparam>
        /// <param name="toSerialize">The object to serialize.</param>
        /// <returns>
        /// The object as XML.
        /// </returns>
        public static string SerializeObject<TSerializationType>(TSerializationType toSerialize)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(TSerializationType));

            using (MemoryStream memoryStream = new MemoryStream())
            {
                serializer.WriteObject(memoryStream, toSerialize);
                return Utf8ByteArrayToString(memoryStream.ToArray());
            }
        }

        /// <summary>
        /// Deserialize an object from an XML string.
        /// </summary>
        /// <param name="xml">The XML to deserialize.</param>
        /// <returns>The deserialized object.</returns>
        public static TSerializationType DeserializeObject<TSerializationType>(string xml) where TSerializationType : new()
        {
            try
            {
                if (string.IsNullOrEmpty(xml))
                    return new TSerializationType();

                DataContractSerializer serializer = new DataContractSerializer(typeof(TSerializationType));

                using (MemoryStream memoryStream = new MemoryStream(StringToUtf8ByteArray(xml)))
                {
                    return (TSerializationType) serializer.ReadObject(memoryStream);
                }
            }
            catch
            {
                return new TSerializationType();
            }
        }

        /// <summary>
        /// Creates the default entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <returns>Default entity value</returns>
        internal static TEntity CreateDefaultEntity<TEntity>() where TEntity : new()
        {
            MultiplePropertyEntityAttribute attribute = GetEntityAttribute(typeof(TEntity));
            return attribute.AllowNullEntities ? default(TEntity) : new TEntity();
        }

        /// <summary>
        /// Converts a byte array of Unicode values (UTF-8 encoded) into a string.
        /// </summary>
        /// <param name="characters">Unicode byte array to be converted.</param>
        /// <returns>A string converted from the Unicode byte array.</returns>
        private static string Utf8ByteArrayToString(byte[] characters)
        {
            return new UTF8Encoding().GetString(characters);
        }

        /// <summary>
        /// Converts a string into a byte array of Unicode values (UTF-8 encoded).
        /// </summary>
        /// <param name="toConvert">The string to be converted.</param>
        /// <returns>A byte array of characters from the string.</returns>
        private static Byte[] StringToUtf8ByteArray(string toConvert)
        {
            return new UTF8Encoding().GetBytes(toConvert);
        }

        #endregion Serialization methods

        #region Composer Issue Fix methods

        /// <summary>
        /// Fixes the multiple property and composer issues.
        /// </summary>
        public static void ConfigureForComposer()
        {
            IHttpHandler handler = HttpContext.Current.Handler;

            if (handler == null || !handler.GetType().Name.Equals("dropit_plugin_extension_ui_edit_propertyeditor_aspx"))
                return;

            Page page = handler as Page;

            if (page == null)
                return;

            page.InitComplete += PageInitComplete;
        }

        private static void PageInitComplete(object sender, EventArgs e)
        {
            IHttpHandler handler = HttpContext.Current.Handler;
            Control control = FindControlRecurisve(handler as Control, "commonPropertyForm", false);

            if (control == null)
                return;

            PropertyInfo renderedPropertiesProperty = control.GetType().GetProperty("RenderedProperties", BindingFlags.Instance | BindingFlags.Public);
            PropertyInfo propertiesProperty = control.GetType().GetProperty("Properties", BindingFlags.Instance | BindingFlags.Public);

            if (renderedPropertiesProperty == null || propertiesProperty == null)
                return;

            PropertyDataCollection properties = renderedPropertiesProperty.GetValue(control, null) as PropertyDataCollection;
            
            if (properties == null)
                return;

            bool hasMultipleProperty = false;

            foreach (PropertyData propertyData in properties)
            {
                PageDefinition pageDefintion = PageDefinition.Load(propertyData.PageDefinitionID);
                Type type = pageDefintion.Type.DefinitionType;

                if (type.BaseType == null || type.BaseType == null || string.IsNullOrEmpty(type.BaseType.FullName) || !type.BaseType.FullName.Contains("ElencySolutions.MultipleProperty.MultiplePropertyBase"))
                    continue;

                hasMultipleProperty = true;
                break;
            }

            if (!hasMultipleProperty)
                return;

            AddFakeProperty(properties);

            properties = propertiesProperty.GetValue(control, null) as PropertyDataCollection;
            AddFakeProperty(properties);
        }

        private static void AddFakeProperty(PropertyDataCollection properties)
        {
            if (properties == null || properties.Any(current => current.Name.Equals(PropertyName)))
                return;

            properties.Add(PropertyName, new MultiplePropertyComposerFixProperty());
            PropertyData propertyData = properties[PropertyName];
            propertyData.Value = string.Empty;
            propertyData.IsRequired = false;
            propertyData.DisplayEditUI = true;
            propertyData.IsLanguageSpecific = true;
            propertyData.OwnerTab = TabDefinition.Load("Extension").ID;
            propertyData.FieldOrder = int.MaxValue;
        }

        #endregion Composer Issue Fix methods

        /// <summary>
        /// Gets the property settings.
        /// </summary>
        /// <param name="propertyData">The property data.</param>
        /// <param name="propertySettingsType">Type of the property settings.</param>
        /// <returns></returns>
        public static IPropertySettings GetPropertySettings(PropertyData propertyData, Type propertySettingsType)
        {
            if (propertyData == null)
                return null;

            if (!propertySettingsType.GetInterfaces().Any(current => current.Equals(typeof(IPropertySettings))))
                return null;

            IPropertyControl propertyDataControl = propertyData.CreatePropertyControl();

            if (propertyDataControl == null)
                return null;

            PropertySettingsAttribute propertySettingsAttribute = propertyData.GetType()
                .GetCustomAttributes(typeof(PropertySettingsAttribute), false).FirstOrDefault() as PropertySettingsAttribute;

            if (propertySettingsAttribute == null)
                return null;

            if (!propertySettingsAttribute.SettingsType.Equals(propertySettingsType))
                return null;

            if (propertyData.SettingsContainer == null)
                return null;

            PropertySettingsWrapper settingsWrapper = propertyData.SettingsContainer.GetSetting(propertySettingsAttribute.SettingsType);
            return settingsWrapper == null ? null : settingsWrapper.PropertySettings;
        }

        public static string CompressString(string text)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(text);
            var memoryStream = new MemoryStream();
            using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
            {
                gZipStream.Write(buffer, 0, buffer.Length);
            }

            memoryStream.Position = 0;

            var compressedData = new byte[memoryStream.Length];
            memoryStream.Read(compressedData, 0, compressedData.Length);

            var gZipBuffer = new byte[compressedData.Length + 4];
            Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length);
            Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
            return Convert.ToBase64String(gZipBuffer);
        }

        public static string DecompressString(string compressedText)
        {
            byte[] gZipBuffer = Convert.FromBase64String(compressedText);
            using (var memoryStream = new MemoryStream())
            {
                int dataLength = BitConverter.ToInt32(gZipBuffer, 0);
                memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4);

                var buffer = new byte[dataLength];

                memoryStream.Position = 0;
                using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
                {
                    gZipStream.Read(buffer, 0, buffer.Length);
                }

                return Encoding.UTF8.GetString(buffer);
            }
        }

        public static bool? EntityHasPropertyType<PropertyType>(PropertyData propertyData) where PropertyType : PropertyData
        {
            Type type = propertyData.GetType().BaseType;
            string name = type.UnderlyingSystemType.FullName;
            string[] nameParts = name.Split(new[] { '[' }, StringSplitOptions.RemoveEmptyEntries);
            string typeName = nameParts.Last().Substring(0);

            if (!typeName.Contains("]"))
                return false;

            typeName = typeName.Substring(0, typeName.IndexOf("]"));
            Type entityType = Type.GetType(typeName);

            if (entityType == null)
                return null;

            foreach (PropertyInfo property in GetEntityTypeProperties(entityType))
            {
                MultiplePropertyEntityPropertyAttribute attribute = GetEntityPropertyAttribute(property);

                if (attribute.Type == typeof(PropertyType))
                    return true;

                Type attributeType = attribute.Type.BaseType;

                if (attributeType == null)
                    continue;

                if (attributeType.Assembly.FullName.StartsWith("ElencySolutions.MultipleProperty") && attributeType.Name.StartsWith("MultiplePropertyBase"))
                {
                    bool? propertyTypeFound = EntityHasPropertyType<PropertyType>(Activator.CreateInstance(attribute.Type) as PropertyData);

                    if (propertyTypeFound.HasValue && propertyTypeFound.Value)
                        return true;
                }

            }

            return null;
        }

        public static string ToPresentationString(string html)
        {
            if (string.IsNullOrEmpty(html))
                return html;

            if (HttpContext.Current.Handler == null)
                return html;

            PropertyXhtmlString propertyXhtmlString = new PropertyXhtmlString(html);
            SimplePage page = HttpContext.Current.Handler as SimplePage;

            if (page == null)
            {
                page = new SimplePage();

                if (HttpContext.Current.Request.UrlReferrer != null)
                {
                    UrlBuilder urlBuilder = new UrlBuilder(HttpContext.Current.Request.UrlReferrer);
                    
                    if (!string.IsNullOrEmpty(urlBuilder.QueryCollection["id"]))
                        page.CurrentPageLink = new PageReference(urlBuilder.QueryCollection["id"]);
                }
            }

            PlaceHolder placeHolder = new PlaceHolder();

            foreach (IStringFragment stringFragment in propertyXhtmlString.Fragments)
                placeHolder.Controls.Add(stringFragment.GetControl(page));

            using (StringWriter stringWriter = new StringWriter())
            {
                using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
                {
                    placeHolder.RenderControl(htmlTextWriter);
                    html = stringWriter.ToString();
                }
            }

            return html;
        }

        //public static object HandleXhtmlStringPropertyTypes(object entity)
        //{
        //    return HandleXhtmlStringPropertyTypes(entity, false);
        //}

        //public static object HandleXhtmlStringPropertyTypes(object entity, bool force)
        //{
        //    string serializedValue = SerializeObject(entity);
        //    bool handleXhtmlStringProperties = (serializedValue.Contains("data-classid=\"") ||
        //                                        serializedValue.Contains("data-hash=\"") ||
        //                                        serializedValue.Contains("data-state=\""));

        //    if ((handleXhtmlStringProperties || force) && HttpContext.Current != null)// && !string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["id"]))
        //        HandleXhtmlStringProperties(entity, force);

        //    return entity;
        //}

        //private static void HandleXhtmlStringProperties(object entity, bool force)
        //{
        //    if (!force && (HttpContext.Current.CurrentHandler == null || (!(HttpContext.Current.CurrentHandler is SimplePage) && !string.Equals(HttpContext.Current.CurrentHandler.GetType().Name, "dropit_plugin_extension_ui_edit_factory_reloadcontentfunction_aspx", StringComparison.OrdinalIgnoreCase))))
        //        return;

        //    if (IsList(entity))
        //    {
        //        foreach (object item in (IList)entity)
        //            HandleXhtmlStringProperties(item, force);
        //        return;
        //    }

        //    foreach (PropertyInfo property in entity.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
        //    {
        //        object value = property.GetValue(entity, null);

        //        if (value == null)
        //            continue;

        //        if (IsList(value))
        //        {
        //            foreach (object item in (IList)value)
        //                HandleXhtmlStringProperties(item, force);

        //            continue;
        //        }

        //        if (property.PropertyType != typeof(string))
        //            continue;

        //        var attribute = GetEntityPropertyAttribute(property);

        //        if (attribute == null || !(attribute.Type == typeof(PropertyXhtmlString) || attribute.Type.IsSubclassOf(typeof(PropertyXhtmlString))))
        //            continue;

        //        string stringValue = value as string;

        //        if (string.IsNullOrEmpty(stringValue))
        //            continue;

        //        PropertyXhtmlString propertyXhtmlString = new PropertyXhtmlString(stringValue);
        //        SimplePage page = HttpContext.Current.Handler as SimplePage;
        //        PlaceHolder placeHolder = new PlaceHolder();

        //        foreach (IStringFragment stringFragment in propertyXhtmlString.StringFragments)
        //        {
        //            placeHolder.Controls.Add(stringFragment.GetControl(page));
        //        }

        //        string webValue = ToPresentationString(placeHolder);
        //        property.SetValue(entity, webValue, null);
        //    }
        //}

    }
}
